package org.paul.library.manager.helper;

import android.content.Context;
import android.content.res.AssetManager;

import javax.net.ssl.*;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

public class URLSSLSocketFactory extends SSLSocketFactory {

    private final SSLSocketFactory delegate;

    public URLSSLSocketFactory(SSLSocketFactory delegate) {
//        try {
//            avoidValidation();//绕过https验证
////            validationCustom();//访问由自定义证书的HTTPs站点 TODO
////            validationDefault();//默认访问由可信机构颁发证书的HTTPs站点 TODO
//        } catch (NoSuchAlgorithmException e) {
//            e.printStackTrace();
//        } catch (KeyManagementException e) {
//            e.printStackTrace();
//        }
        this.delegate = delegate;
    }
    // 根据证书文件生成keystore
    private KeyStore certTrusted(Context context)
            throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, NoSuchProviderException {
        // 从资源文件中获取.cer证书文件
        AssetManager assetManager = context.getAssets();
        InputStream inputStream = assetManager.open("12306.cer");//replace your fileName here
        try {
            // 读取证书
            CertificateFactory cerFactory = CertificateFactory.getInstance("X.509");
            java.security.cert.Certificate cer = cerFactory.generateCertificate(inputStream);
            // 创建一个证书库，并将证书导入证书库
            KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
            keyStore.load(null, null);
            keyStore.setCertificateEntry("12306", (java.security.cert.Certificate) cer);
            return keyStore;
        } finally {
            inputStream.close();
        }
    }

    /**
     * 访问由可信任机构颁发证书的https站点
     *
     * @throws KeyManagementException
     * @throws NoSuchAlgorithmException
     */
    private void validationDefault() throws KeyManagementException, NoSuchAlgorithmException {
        SSLContext localSSLContext = SSLContext.getInstance("TLS");
        localSSLContext.init(null, null, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(new URLSSLSocketFactory(localSSLContext.getSocketFactory()));
    }

    /**
     * 绕过https 证书验证
     *
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    private void avoidValidation()
            throws NoSuchAlgorithmException, KeyManagementException {
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }

                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
                    }

                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
                    }

                }
        };
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, trustAllCerts, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(new URLSSLSocketFactory(sslContext.getSocketFactory()));

    }
    @Override
    public String[] getDefaultCipherSuites() {
        return delegate.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return delegate.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket(final Socket socket, final String host, final int port, final boolean autoClose)
            throws IOException {
        final Socket underlyingSocket = delegate.createSocket(socket, host, port, autoClose);
        return overrideProtocol(underlyingSocket);
    }

    @Override
    public Socket createSocket(final String host, final int port) throws IOException {
        final Socket underlyingSocket = delegate.createSocket(host, port);
        return overrideProtocol(underlyingSocket);
    }

    @Override
    public Socket createSocket(final String host, final int port, final InetAddress localAddress, final int localPort)
            throws
            IOException {
        final Socket underlyingSocket = delegate.createSocket(host, port, localAddress, localPort);
        return overrideProtocol(underlyingSocket);
    }

    @Override
    public Socket createSocket(final InetAddress host, final int port) throws IOException {
        final Socket underlyingSocket = delegate.createSocket(host, port);
        return overrideProtocol(underlyingSocket);
    }

    @Override
    public Socket createSocket(final InetAddress host, final int port, final InetAddress localAddress, final int localPort)
            throws
            IOException {
        final Socket underlyingSocket = delegate.createSocket(host, port, localAddress, localPort);
        return overrideProtocol(underlyingSocket);
    }

    private Socket overrideProtocol(final Socket socket) {
        if (!(socket instanceof SSLSocket)) {
            throw new RuntimeException("An instance of SSLSocket is expected");
        }
        ((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1", "TLSv1.1", "TLSv1.2"});
        return socket;
    }
}
